package com.isyscore.os.etl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isyscore.boot.login.LoginUserManager;
import com.isyscore.boot.mybatis.PageRequest;
import com.isyscore.device.common.model.RespDTO;
import com.isyscore.os.core.entity.Resource;
import com.isyscore.os.core.exception.DataFactoryException;
import com.isyscore.os.core.exception.ErrorCode;
import com.isyscore.os.core.mapper.ResourceMapper;
import com.isyscore.os.core.model.entity.JobConfig;
import com.isyscore.os.core.util.InitiallyUtils;
import com.isyscore.os.etl.service.DmcService;
import com.isyscore.os.etl.service.JobConfigService;
import com.isyscore.os.etl.service.ResourceService;
import com.isyscore.os.permission.common.constants.PermissionConstants;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 *  服务实现类
 *
 * @author felixu
 * @since 2021-08-03
 */
@Service
@RequiredArgsConstructor
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements ResourceService {

    private final JobConfigService jobConfigService;

    private final DmcService dmcService;

    private final LoginUserManager loginUserManager;

    //checked
    @Override
    public Resource getResourceByIdAndCheck(String id) {
        final LambdaQueryWrapper<Resource> query = Wrappers.<Resource>lambdaQuery().eq(Resource::getId, id).and(wrapper -> {
            wrapper.eq(Resource::getTenantId, loginUserManager.getCurrentTenantId())
                    .or().eq(Resource::getTenantId, PermissionConstants.GLOBAL_BUSINESS_DATA_TENANT_ID_KEY);
        });

        Resource resource = InitiallyUtils.markInitially(() -> getOne(query));
        if (resource == null)
            throw new DataFactoryException(ErrorCode.RESOURCE_NOT_FOUND);
        return resource;
    }

    //checked
    @Override
    public Resource createResource(Resource resource) {
        produce(resource);
        check(resource, false);
        save(resource);
        return resource;
    }

    //checked
    @Override
    public Resource updateResource(Resource resource) {
        produce(resource);
        check(resource, true);
        updateById(resource);
        return resource;
    }

    //checked
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Resource deleteResource(String id) {
        Resource resource = getResourceByIdAndCheck(id);
        if (Objects.equals(PermissionConstants.GLOBAL_BUSINESS_DATA_TENANT_ID_KEY, resource.getTenantId())) {
            throw new DataFactoryException(ErrorCode.RESOURCE_NOT_ALLOWED);
        }
        List<JobConfig> list = jobConfigService.list(
                Wrappers.<JobConfig>lambdaQuery()
                .like(JobConfig::getExtJarPath, resource.getUrl())
                .or()
                .like(JobConfig::getCustomJarUrl, resource.getUrl())
        );
        if (CollectionUtils.isEmpty(list)) {
            removeById(id);
            // 移除资源
            String url = resource.getUrl();
            int index = url.indexOf("custom");
            RespDTO<Boolean> result = dmcService.deleteFileByPath(url.substring(index));
            if (result == null || !Boolean.TRUE.equals(result.getData()))
                throw new DataFactoryException(ErrorCode.RESOURCE_DELETE_FAILED);
        }else {
            throw new DataFactoryException(ErrorCode.CANNOT_DELETE,
                    list.parallelStream().map(JobConfig::getJobName).collect(Collectors.joining(",")));
        }
        return resource;
    }

    //checked
    private void check(Resource resource, boolean isUpdate) {
        LambdaQueryWrapper<Resource> wrapper = Wrappers.<Resource>lambdaQuery()
                .eq(Resource::getName, resource.getName());
        Resource one = getOne(wrapper);
        if (one != null && (!isUpdate || !one.getId().equals(resource.getId())))
            throw new DataFactoryException(ErrorCode.RESOURCE_NAME_EXIST);
    }

    /**
     * 3.1.0处理逻辑，后端处理，之后前端处理
     * 处理资源中的ip为service,38080端口替换成37000
     * @param resource 资源对象
     */
    private void produce(Resource resource){
        try {
            String url = resource.getUrl();
            int slashIndex=url.indexOf("//");
            int colonIndex=url.indexOf(":",slashIndex);
            String ip= url.substring(slashIndex+2,colonIndex);
            resource.setUrl(url.replaceFirst(ip,"isc-dmc-service").replaceFirst("38080","37000"));
        }catch (Exception e){
            log.error("处理资源字段失败"+e.getMessage(),e);
        }
    }

    //checked
    @Override
    public IPage<Resource> list(Resource resource, PageRequest page) {
        final LambdaQueryWrapper<Resource> query = Wrappers.<Resource>lambdaQuery(resource)
                .eq(Resource::getTenantId, loginUserManager.getCurrentTenantId())
                .or()
                .eq(Resource::getTenantId, PermissionConstants.GLOBAL_BUSINESS_DATA_TENANT_ID_KEY);
        return InitiallyUtils.markInitially(() -> page(page.toPage(), query));
    }
}
